package site.addzero.cli.autoinit.unix

import org.koin.core.annotation.Single
import site.addzero.cli.platform.PlatformTools
import site.addzero.cli.platform.PlatformType
import site.addzero.cli.platform.runCmd
import site.addzero.cli.setting.SettingContext
import site.addzero.task.InitTask
import java.io.File

/**
 * Zulu JDK 自动初始化类
 * 负责下载 Zulu JDK 8, 17, 21 并配置 JAVA_HOME
 */
@Single
class AutoInitZuluJdk : InitTask {
    override val support: Boolean = isUnixPlatform()

    // 根据平台确定下载 URLs
    private fun getZuluJdkUrls(): Map<Int, String> {
        val platform = PlatformTools.getPlatformType()
        val arch = System.getProperty("os.arch")
        val isArm = arch.contains("aarch64") || arch.contains("arm")

        return when (platform) {
            PlatformType.MACOS -> mapOf(
                8 to if (isArm) "https://cdn.azul.com/zulu/bin/zulu8.76.0.17-ca-jdk8.0.402-macosx_aarch64.tar.gz" 
                    else "https://cdn.azul.com/zulu/bin/zulu8.76.0.17-ca-jdk8.0.402-macosx_x64.tar.gz",
                17 to if (isArm) "https://cdn.azul.com/zulu/bin/zulu17.48.15-ca-jdk17.0.10-macosx_aarch64.tar.gz" 
                    else "https://cdn.azul.com/zulu/bin/zulu17.48.15-ca-jdk17.0.10-macosx_x64.tar.gz",
                21 to if (isArm) "https://cdn.azul.com/zulu/bin/zulu21.36.17-ca-jdk21.0.6-macosx_aarch64.tar.gz" 
                    else "https://cdn.azul.com/zulu/bin/zulu21.36.17-ca-jdk21.0.6-macosx_x64.tar.gz"
            )
            PlatformType.LINUX -> mapOf(
                8 to if (isArm) "https://cdn.azul.com/zulu/bin/zulu8.76.0.17-ca-jdk8.0.402-linux_aarch64.tar.gz" 
                    else "https://cdn.azul.com/zulu/bin/zulu8.76.0.17-ca-jdk8.0.402-linux_x64.tar.gz",
                17 to if (isArm) "https://cdn.azul.com/zulu/bin/zulu17.48.15-ca-jdk17.0.10-linux_aarch64.tar.gz" 
                    else "https://cdn.azul.com/zulu/bin/zulu17.48.15-ca-jdk17.0.10-linux_x64.tar.gz",
                21 to if (isArm) "https://cdn.azul.com/zulu/bin/zulu21.36.17-ca-jdk21.0.6-linux_aarch64.tar.gz" 
                    else "https://cdn.azul.com/zulu/bin/zulu21.36.17-ca-jdk21.0.6-linux_x64.tar.gz"
            )
            else -> emptyMap()
        }
    }

    private fun getZuluJdkFilenames(): Map<Int, String> {
        val platform = PlatformTools.getPlatformType()
        val arch = System.getProperty("os.arch")
        val isArm = arch.contains("aarch64") || arch.contains("arm")

        return when (platform) {
            PlatformType.MACOS -> mapOf(
                8 to if (isArm) "zulu8.76.0.17-ca-jdk8.0.402-macosx_aarch64.tar.gz" 
                    else "zulu8.76.0.17-ca-jdk8.0.402-macosx_x64.tar.gz",
                17 to if (isArm) "zulu17.48.15-ca-jdk17.0.10-macosx_aarch64.tar.gz" 
                    else "zulu17.48.15-ca-jdk17.0.10-macosx_x64.tar.gz",
                21 to if (isArm) "zulu21.36.17-ca-jdk21.0.6-macosx_aarch64.tar.gz" 
                    else "zulu21.36.17-ca-jdk21.0.6-macosx_x64.tar.gz"
            )
            PlatformType.LINUX -> mapOf(
                8 to if (isArm) "zulu8.76.0.17-ca-jdk8.0.402-linux_aarch64.tar.gz" 
                    else "zulu8.76.0.17-ca-jdk8.0.402-linux_x64.tar.gz",
                17 to if (isArm) "zulu17.48.15-ca-jdk17.0.10-linux_aarch64.tar.gz" 
                    else "zulu17.48.15-ca-jdk17.0.10-linux_x64.tar.gz",
                21 to if (isArm) "zulu21.36.17-ca-jdk21.0.6-linux_aarch64.tar.gz" 
                    else "zulu21.36.17-ca-jdk21.0.6-linux_x64.tar.gz"
            )
            else -> emptyMap()
        }
    }

    /**
     * 执行 Zulu JDK 初始化任务
     */
    override suspend fun asynctask(): Boolean {
        if (!support) {
            println("当前平台不支持 Zulu JDK 自动初始化")
            return true
        }

        println("正在初始化 Zulu JDK...")

        // 确保 useful 目录存在
        val usefulDir = File(SettingContext.USEFUL_SOFT_DIR)
        if (!usefulDir.exists()) {
            usefulDir.mkdirs()
        }

        // 获取平台相关的下载 URLs
        val zuluJdkUrls = getZuluJdkUrls()
        val zuluJdkFilenames = getZuluJdkFilenames()

        // 下载并解压各个版本的 JDK
        val installedJdks = mutableMapOf<Int, String>()
        for ((version, url) in zuluJdkUrls) {
            try {
                val filename = zuluJdkFilenames[version] ?: continue
                val jdkPath = downloadAndExtractJdk(version, url, filename, usefulDir.absolutePath)
                if (jdkPath != null) {
                    installedJdks[version] = jdkPath
                    println("Zulu JDK $version 安装成功: $jdkPath")
                } else {
                    println("Zulu JDK $version 安装失败")
                }
            } catch (e: Exception) {
                println("安装 Zulu JDK $version 时出错: ${e.message}")
            }
        }

        // 配置 JAVA_HOME 为 JDK 17
        if (installedJdks.containsKey(17)) {
            configureJavaHome(installedJdks[17]!!)
        } else if (installedJdks.isNotEmpty()) {
            // 如果没有 JDK 17，使用第一个安装的版本
            val firstJdk = installedJdks.values.first()
            configureJavaHome(firstJdk)
        }

        return true
    }

    /**
     * 下载并解压 JDK
     * @param version JDK 版本
     * @param url 下载 URL
     * @param filename 文件名
     * @param destDir 目标目录
     * @return 解压后的 JDK 路径，如果失败则返回 null
     */
    private fun downloadAndExtractJdk(version: Int, url: String, filename: String, destDir: String): String? {
        try {
            val downloadPath = "$destDir${File.separator}$filename"
            val extractDir = "$destDir${File.separator}zulu$version"

            // 检查是否已经下载并解压
            if (File(extractDir).exists()) {
                println("Zulu JDK $version 已存在，跳过下载")
                // 返回 bin 目录的父目录（JDK 根目录）
                return findJdkRootDir(extractDir)
            }

            println("正在下载 Zulu JDK $version...")
            // 静默下载
            val downloadResult = "curl -s -L -o \"$downloadPath\" \"$url\"".runCmd()
            if (!downloadResult.isSuccess()) {
                println("下载 Zulu JDK $version 失败: ${downloadResult.error}")
                return null
            }

            println("正在解压 Zulu JDK $version...")
            // 创建解压目录
            File(extractDir).mkdirs()
            // 解压文件
            val extractResult = "tar -xzf \"$downloadPath\" -C \"$extractDir\" --strip-components=1".runCmd()
            if (!extractResult.isSuccess()) {
                println("解压 Zulu JDK $version 失败: ${extractResult.error}")
                return null
            }

            // 删除下载的压缩文件
            File(downloadPath).delete()

            // 返回 JDK 根目录
            return findJdkRootDir(extractDir)
        } catch (e: Exception) {
            println("下载并解压 Zulu JDK $version 时出错: ${e.message}")
            return null
        }
    }

    /**
     * 查找 JDK 根目录
     * @param extractDir 解压目录
     * @return JDK 根目录路径
     */
    private fun findJdkRootDir(extractDir: String): String {
        val dir = File(extractDir)
        if (!dir.exists() || !dir.isDirectory) return extractDir

        // 查找包含 bin 目录的子目录
        dir.listFiles()?.forEach { file ->
            if (file.isDirectory && File(file, "bin").exists() && File(file, "bin/java").exists()) {
                return file.absolutePath
            }
        }

        // 如果没找到特定结构，返回解压目录
        return extractDir
    }

    /**
     * 配置 JAVA_HOME 环境变量
     * @param jdkPath JDK 路径
     */
    private fun configureJavaHome(jdkPath: String) {
        try {
            val homeDir = System.getProperty("user.home")
            val shell = System.getenv("SHELL") ?: "/bin/bash"
            val shellConfigFiles = when {
                shell.contains("zsh") -> listOf("$homeDir/.zshrc", "$homeDir/.zprofile")
                else -> listOf("$homeDir/.bashrc", "$homeDir/.bash_profile")
            }

            // 在所有可能的 shell 配置文件中更新 JAVA_HOME
            for (shellConfigFile in shellConfigFiles) {
                val configFile = File(shellConfigFile)
                // 如果文件不存在，创建它
                if (!configFile.exists()) {
                    configFile.parentFile?.mkdirs()
                    configFile.createNewFile()
                }

                // 读取文件内容
                val lines = configFile.readLines().toMutableList()
                var javaHomeFound = false
                var pathFound = false

                // 查找并更新 JAVA_HOME
                for (i in lines.indices) {
                    if (lines[i].startsWith("export JAVA_HOME=")) {
                        lines[i] = "export JAVA_HOME=\"$jdkPath\""
                        javaHomeFound = true
                        break
                    }
                }

                // 如果没有找到 JAVA_HOME，添加它
                if (!javaHomeFound) {
                    lines.add(0, "export JAVA_HOME=\"$jdkPath\"")
                }

                // 查找并更新 PATH 中的 JAVA_HOME 引用
                for (i in lines.indices) {
                    if (lines[i].startsWith("export PATH=") && lines[i].contains("JAVA_HOME")) {
                        // 确保 PATH 包含 JAVA_HOME/bin
                        if (!lines[i].contains("\$JAVA_HOME/bin")) {
                            lines[i] = "export PATH=\"\$JAVA_HOME/bin:\$PATH\""
                        }
                        pathFound = true
                        break
                    }
                }

                // 如果没有找到包含 JAVA_HOME 的 PATH，添加它
                if (!pathFound) {
                    lines.add(1, "export PATH=\"\$JAVA_HOME/bin:\$PATH\"")
                }

                // 写回文件
                configFile.writeText(lines.joinToString("\n") + "\n")
            }

            println("JAVA_HOME 已配置为: $jdkPath")
            println("请重新加载您的 shell 配置文件或重新打开终端以使更改生效")
        } catch (e: Exception) {
            println("配置 JAVA_HOME 时出错: ${e.message}")
        }
    }

    /**
     * 检查是否为 Unix 平台（Linux 或 macOS）
     * @return 是否为 Unix 平台
     */
    private fun isUnixPlatform(): Boolean {
        return when (PlatformTools.getPlatformType()) {
            PlatformType.LINUX, PlatformType.MACOS -> true
            else -> false
        }
    }
}